package com.yyaccp.easybuy.security.service;

import com.yyaccp.easybuy.security.vo.AuthProperties;
import com.yyaccp.easybuy.security.vo.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 基于url模式进行权限控制
 * 每次访问控制器前，比较用户的权限集合（url集合）中是否包含了该控制器的路径
 */
@Service("rbacService")
@ConditionalOnProperty(name = "auth.pattern", havingValue = "url")
@Slf4j
public class RbacServiceImpl implements RbacService {
    private AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    private AuthProperties authProperties;

    @Override
    public boolean hasPerms(HttpServletRequest request, Authentication authentication) {
        boolean hasPerm = false;
        String requestURI = getRequestURI(request);
        Object principal = authentication.getPrincipal();
        if(principal != null && principal instanceof UserDetails) {
            LoginUser loginUser = (LoginUser) principal;
            List<String> urls = loginUser.getUrls();
            log.info("用户urls:{}", urls);
            for(String url: urls) {
                if(antPathMatcher.match(url, requestURI)) {
                    hasPerm = true;
                    break;
                }
            }
        }
        log.info("鉴权结果【{}】，{}", requestURI, hasPerm);
        return hasPerm;

    }

    /**
     * 如果是restful，从数据库加载url时，需要把method和url连接成GET_/emp/{id}以便鉴权
     * @param request
     * @return
     */
    private String getRequestURI(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        if(authProperties.isRestful()) {
            return request.getMethod().toUpperCase() + "_" + requestURI;
        }
        return requestURI;
    }

}
